package com.bdqn.gulimall.search.thread;

import java.util.concurrent.*;

/**
 * ThreadTest
 * 测试多线程
 *
 * @author f
 * @since 2022/2/25
 */
public class ThreadTest {
    //当前系统中池只有一两个 固定10个任务数量的空闲线程池
    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    /**
     * 启动异步任务
     *
     * @param args
     */
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main……start……");
        // runAsync()方法选指定的线程池（两参数）
        // 1.CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
        //     System.out.println("当前线程：" + Thread.currentThread().getId());
        //     int i = 10 / 2;
        //     System.out.println("运行结果：" + i);
        // }, executor);
        // CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
        //     System.out.println("当前线程：" + Thread.currentThread().getId());
        //     int i = 10 / 0;
        //     System.out.println("运行结果：" + i);
        //     return i;
        //     // whenComplete()方法，成功之后做的事(回调方法）
        // }, executor).whenComplete((result,excption)->{
        //     //虽然得到异常信息，但是无法修改返回数据
        //     System.out.println("异步任务成功，完成了……功能,结果是：" + result + "异常是：" + excption);
        //
        //          R.apply(T t);
        // }).exceptionally(throwable -> {
        //     // exceptionally()：感知异常，异常返回方法，此处自定义出现异常返回的默认值为10
        //     return 10;
        // });

        //方法执行完成后的处理
        // CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
        //     System.out.println("当前线程：" + Thread.currentThread().getId());
        //     int i = 10 / 4;
        //     System.out.println("运行结果：" + i);
        //     return i;
        //
        //      R.apply(T t, U u);
        // }, executor).handle((result,exception)->{
        //     if (result != null){
        //         return result * 2;
        //     }
        //     if (exception != null){
        //         return 0;
        //     }
        //     return 0;
        // });

        /**
         * 线程串行化
         * 1.thenRun:不能获取到上一步的执行结果，无返回值
         * 接在第一个线程池executor后面
         * .thenRunAsync(() -> {
         *             System.out.println("任务二已启动");
         *         }, executor);
         *
         * 2.thenAcceptAsync()方法：能接收上一步（次）结果，但是无返回值
         * .thenAcceptAsync(result->{
         *             System.out.println("任务二已启动" + result);
         *         }, executor);
         *
         * R apply(T t);
         * 3.thenApplyAsync()方法，能获取到上一次运行的结果，有返回值
         */
        // CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
        //     System.out.println("当前线程：" + Thread.currentThread().getId());
        //     int i = 10 / 4;
        //     System.out.println("运行结果：" + i);
        //     return i;
        //
        // }, executor).thenApplyAsync(result -> {
        //     System.out.println("任务二已启动" + result);
        //
        //     return "Hello " + result;
        // }, executor);

        /**
         *
         */
        // CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
        //     System.out.println("任务1线程：" + Thread.currentThread().getId());
        //     int i = 10 / 4;
        //     System.out.println("任务1结束：" + i);
        //     return i;
        // }, executor);
        //
        //
        // CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
        //     System.out.println("任务2线程：" + Thread.currentThread().getId());
        //     try {
        //         Thread.sleep(2000);
        //         System.out.println("任务2结束：");
        //     } catch (InterruptedException e) {
        //         e.printStackTrace();
        //     }
        //     return "你好";
        // }, executor);

        /**
         * 任务1合并任务2（任务3）
         */


        // 1.runAfterBothAsync()方法无法感知前两个的结果
        // future01.runAfterBothAsync(future02,()->{
        //     System.out.println("任务3开始……");
        // },executor);


        // 2.void accept(T t,U u);
        // future01.thenAcceptBothAsync(future02,(f1,f2)->{
        //         System.out.println("任务3开始……之前的结果是" + f1 + "和" + f2);
        //     },executor);


        // 3.thenCombineAsync()
        //R apply(T t, U u);
        // CompletableFuture<String> future = future01.thenCombineAsync(future02, (f1, f2) -> {
        //     return f1 + "和" + f2 + " 嘻嘻哈哈";
        // }, executor);
        //


        /**
         * 两任务中有一个完成就可以执行任务3
         */
        //1.thenAcceptBothAsync()方法 不感知结果，自己也无返回值
        // future01.runAfterEitherAsync(future02,()-> {
        //     System.out.println("任务3开始……");
        // }, executor);


        //2.acceptEitherAsync()方法 能感知结果，自己没有返回值 前两个方法返回类型要相同，此处皆为Object
        // future01.acceptEitherAsync(future02, (result) -> {
        //     System.out.println("任务3开始……之前的结果是：" + result);
        // }, executor);


        //3.applyToEitherAsync()方法 能感知结果，并且有返回值
        // CompletableFuture<String> future = future01.applyToEitherAsync(future02, (result) -> {
        //     System.out.println("任务3开始……之前的结果是：" + result);
        //     return result.toString() + " 哭泣";
        // }, executor);

        /**
         * 多任务组合，模拟获取各类信息
         */
        CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的图片信息");
            return "uii.jpg";
        },executor);

        CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的属性");
            return "天蓝+512G";
        },executor);

        CompletableFuture<String> futureDesc = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
                System.out.println("查询商品的介绍信息");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "三星";
        },executor);

        // futureImg.get();
        // futureAttr.get();
        // futureDesc.get();

        /**
         * allOf()方法
         * 所有都须执行成功
         */
        // CompletableFuture<Void> allOf = CompletableFuture.allOf(futureImg, futureAttr, futureDesc);


        /**
         * anyOf()方法
         * 一个执行成功就行
         */
        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(futureImg, futureAttr, futureDesc);
        anyOf.get();//等待所有结果完成

        /**
         * allOf()方法
         */
        // System.out.println("main……end……" + futureImg.get() + " " + futureAttr.get()
        //         + " " + futureDesc.get());
        // }


        /**
         * anyOf()方法
         * 哪个成功了都能获取到
         */
        System.out.println("main……end……" + anyOf.get());
        }

        public void thread (String[]args) throws ExecutionException, InterruptedException {
            System.out.println("main……start……");
            /**
             * 1）、继承Thread类
             *         Thread01 thread = new Thread01();
             *         thread.start();//启动线程
             *
             * 2）、实现Runnable 接口
             *         Runnable01 runnable01 = new Runnable01();
             *         new Thread(runnable01).start();
             * 3）、实现Callable 接口+ FutureTask （可以拿到返回结果，可以处理异常）
             *         FutureTask<Integer> futureTask = new FutureTask<>(new Callable01());
             *         new Thread(futureTask).start();
             *
             *         //阻塞效果，等待整个线程执行完成，获取返回结果
             *         //记得抛出get()方法的异常
             *         Integer integer = futureTask.get();
             *         System.out.println("main……end……" + integer);
             * 4）、线程池
             *  给线程池提交任务，它会开启一个线程
             *  service.execute(new Runnable01());
             *
             *  4.1.创建
             *      1.Executors
             *      2.new ThreadPoolExecutor
             *
             *  Future:可以获取到异步结果
             *
             *  区别
             *      1、2无法得到返回值，3可以获得返回值
             *      1、2、3都不能控制资源，每new一个Thread都会立即执行
             *      4可以控制资源，性能稳定
             */
            //应将所有多线程的异步任务交由线程池执行

            //当前系统中池只有一两个 固定10个任务数量的空闲线程池
            /**
             * 七大参数
             * corePoolSize：[5]核心线程数；线程池创建好之后就准备就绪的线程数量，等待接收异步任务执行，默认不回收，一直
             * 存在，（可修改，设置allowCoreThreadTimeOut）
             *         []中数字代表核心线程数，调用start()方法后启动 Thread thread = new Thread();   thread.start();
             *
             * maximumPoolSize:最大线程数量  控制资源
             *
             * keepAliveTime：保持存活时间
             * 当线程数大于核心时，释放空闲的线程[maximumPoolSize(核心线程数)-corePoolSize(最大线程数量)，
             * 因为核心线程默认不回收]
             * 当线程数大于核心时，这是多余的空闲线程在终止前等待新任务的最长时间。
             * @param unit {@code keepAliveTime} 参数的时间单位 @param workQueue 用于在执行任务之前保存任务的队列。
             * 此队列将仅保存由 {@code execute} 方法提交的 {@code Runnable} 任务。
             *
             * TimeUnit:时间单位
             *
             * BlockingQueue<Runnable> workQueue：阻塞队列 如果当前有很多任务，就会将多的放在队列中
             * 只要有线程空闲，就会去队列里取出新的任务继续执行
             * 用于在执行任务之前保存任务的队列。此队列将仅保存由 {@code execute} 方法提交的 {@code Runnable} 任务。
             *
             * threadFactory:线程的创建工厂
             * 执行器创建新线程时使用的工厂
             *
             * RejectedExecutionHandler handler:如果队列满了，按照我们指定的拒绝策略拒绝执行任务
             * 由于达到线程边界和队列容量而阻塞执行时使用的处理程序
             *
             *
             * 工作顺序：
             * core：核心线程数简写
             * quece：队列数量简写
             *
             * 1. 线程池创建，准备好 core 数量的核心线程，准备接受任务
             * 1.1 core 满了，就将再进来的任务放入阻塞队列中。空闲的core 就会自己去阻塞队列获取任务执行
             * 1.2 阻塞队列满了，就直接开新线程执行，最大只能开到 max 指定的数量
             * 1.3 max满了就用RejectedExecutionHandler拒绝任务
             * 1.4 max都执行完成，有很多空闲，在keepAliveTime 指定的时间后，释放max-core这些线程
             *
             * quece：队列数量简写
             * 举例：一个线程池core 7； max 20 ，queue：50，100 并发进来怎么分配的；
             * 先有7个能直接得到执行，接下来50个进入队列排队，在多开13个继续执行。现在70个被安排上了。剩下30个默认拒绝策略。
             * 如不想抛弃还要执行，使用CallerRunsPolicy策略
             */
            ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 200,
                    //10秒没有新任务，则释放这些线程
                    10, TimeUnit.SECONDS,
                    //LinkedBlockingDeque<>()方法的容量是Interger类型的最大值 this(Integer.MAX_VALUE); 内存不够
                    new LinkedBlockingDeque<>(100000),
                    //defaultThreadFactory 默认的线程工厂
                    Executors.defaultThreadFactory(),
                    //AbortPolicy()方法，直接丢弃新来的任务
                    new ThreadPoolExecutor.AbortPolicy());

            /**
             * 常见的四种线程池创建方式
             */
            //core:0,所有线程都可以回收 创建一个可缓存线程池，如果线程池长度超过处理需要，可灵活回收空闲线程，若无可回收，则新建线程
            // Executors.newCachedThreadPool();
            //
            // //固定大小，core=max 都不可回收
            // Executors.newFixedThreadPool();
            //
            // //定时任务的线程池
            // Executors.newScheduledThreadPool();
            //
            // //单线程的线程池，后台从队列中获取任务，挨个执行
            // Executors.newSingleThreadExecutor();


            System.out.println("main……end……");
        }

        /**
         * 继承 Thread 类
         */
        public static class Thread01 extends Thread {
            @Override
            public void run() {
                System.out.println("当前线程：" + Thread.currentThread().getId());
                int i = 10 / 2;
                System.out.println("运行结果：" + i);
            }
        }

        /**
         * 实现Runnable 接口
         */
        public static class Runnable01 implements Runnable {

            @Override
            public void run() {
                System.out.println("当前线程：" + Thread.currentThread().getId());
                int i = 10 / 2;
                System.out.println("运行结果：" + i);

            }
        }

        /**
         * 实现Callable 接口+ FutureTask （可以拿到返回结果，可以处理异常）
         */
        public static class Callable01 implements Callable {
            @Override
            public Object call() throws Exception {
                System.out.println("当前线程：" + Thread.currentThread().getId());
                int i = 10 / 2;
                System.out.println("运行结果：" + i);
                return i;
            }
        }
    }
